home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-10-27 | 48.7 KB | 1,287 lines |
- Spellcaster presents:
-
-
- TTTTTTTTTT HH HH EEEEEEEEEE MM MM AAAA GGGGGGGGG
- TT HH HH EE MMM MMM AA AA GG
- TT HH HH EE MM M M MM AA AA GG
- TT HHHHHHHHHH EEEEEE MM MM MM AAAAAAAA GG
- TT HH HH EE MM MM AA AA GG GGGG
- TT HH HH EE MM MM AA AA GG GG
- TT HH HH EEEEEEEEEE MM MM AA AA GGGGGGGG
-
- Issue 3
- 4-10-95
-
-
-
- ■ Index
-
- 1. Introduction
- 1.1. About the magazine
- 1.2. About the author
- 1.3. Distribution
- 1.4. Contribuitions
- 1.5. Hellos and greets
- 2. Resolution of your homework
- 3. Procedures and functions
- 3.1. What are they ?
- 3.2. How to use
- 3.3. Global and local variables
- 3.4. Parameters
- 3.5. Functions
- 4. Introduction to assembly
- 4.1. Segments and offsets
- 4.2. Registers
- 4.3. The stack
- 4.4. The flags
- 4.5. More about segments
- 4.6. Basic instructions
- 5. Graphics, part 2 : The palette
- 5.1. Introduction
- 5.2. What's the palette
- 5.3. How to set and get the palette ?
- 5.4. The retrace
- 5.5. Palette effects
- 5.5.1. Rotations
- 5.5.2. Fades
- 5.5.3. The static screen
- 6. Points of View
- 7. The adventures of Spellcaster, part 3.
-
-
- ■ Introduction
-
- ■ About the magazine
-
- So, we've finally reached issue 3... A small step to me, but a great step
- to computerkind...
- This issue is packed with information... We have the second part of our
- mode 13h tutorial (dedicated to palettes), plus an article on procedures and
- functions for the begginers out there, besides other stuff.
- This issue also has a special bonus... You probably have noticed that when
- you decompress 'The Mag', you don't get only this text file, but a lot of
- other files... They are a part of a small demo I did in two days, especially
- for the mag. To run the demo, type in 'CBLIND' at the DOS prompt. I made it
- to acompany this week's mode 13h tutorial, to demonstrate the potencial of the
- palette, and the wonderfull effects you can achieve with it, if you think for
- a bit... The hardest thing to do in the demo was to think of the effects.
- Coding them is easy (except the cross-fade). The effects will be explained in
- the Graphics section of 'The Mag'.
- This magazine is dedicated to all the programmers and would-be programmers
- out there, to those who wish to learn how to program anything, from demos
- to games, passing through utilities and all sort of thing your mind can
- think of.
-
- When you read this magazine, I'll assume some things. First, I assume you
- have Borland's Turbo Pascal, version 6 and upwards. I'll also think you have
- a 80386 (or 386 for short; a 486 would be even better), a load of patience
- and a sense of humor. This last is almost essencial, because I don't receive
- any money for doing this, so I must have fun doing it. I will also take for
- certain you have the 9th grade (or equivelent).
-
- As I stated above, this magazine will be made especially for those who don't
- know where to get information, or want it all in the same place, and to those
- who want to learn how to program, so I'll try to build knowledge, building up
- your skills issue by issue. If you sometimes fail to grasp some concept, don't
- despair; try to work it out.
- That's what I did... Almost everything I know was learnt from painfull
- experience. If you re-re-re-read the article, and still can't understand it,
- just drop a line, by mail, or just plain forget it. Most of the things I
- try to teach here aren't linked to each other (unless I say so), so if you
- don't understand something, skip it and go back to it some weeks later. It
- should be clearer for you then. Likewise, if you see any terms or words you
- don't understand, follow the same measures as before.
-
- Ok, as I'm earing the Net gurus and other god-like creatures talking
- already, I'm just going to explain why I use Pascal.
- For starters, Pascal is a very good language, ideal for the beginner, like
- BASIC (yech!), but it's powerfull enough to make top-notch programms.
- Also, I'll will be using assembly language in later issues, and Pascal makes
- it so EASY to use.
- Finally, if you don't like my choice of language, you can stop whining. The
- teory behind each article is very simple, and common with any of the main
- languages (C, C++, Assembly - Yes, that's true... BASIC isn't a decent
- language).
-
- Just one last thing... The final part of the magazine is a little story
- made up by my distorted mind. It's just a little humor I like to write, and
- it hasn't got nothing to do with programming (well, it has a little), but,
- as I said before, I just like to write it.
-
- ■ About the author
-
- Ok, so I'm a little egocentric, but tell me... If you had the trouble of
- writing hundreds of lines, wouldn't you like someone to know you, even by
- name ?
-
- My name is Diogo de Andrade, alias Spellcaster, and I'm the creator,
- editor and writer of this magazine.
- I live in a small town called Setúbal, just near Lisbon, the capital of
- Portugal... If you don't know where it is, get an encyclopedia, and look for
- Europe. Then, look for Spain. Next to it, there's Portugal, and Setúbal is in
- the middle.
-
- I'm 18 years old, and I just made it in to the university (if you do want
- to know, I'm in the Technical Institute of Lisbon, Portugal), so I'm not
- a God-Like creature, with dozens of years of practice (I only program by
- eight years now, and I started in a Spectrum, progressing later to an Amiga.
- I only program in the PC for a year or so), with a mega-computer (I own a
- 386SX, 16 Mhz), that wear glasses with lens that look like the bottom of a
- bottle (I use glasses, but only sometimes), that has his head bigger than a
- pumpkin (I have a normal sized head) and with an IQ of over 220 (mine is
- actually something like 180). I can program in C, C++, Pascal, Assembly
- and even BASIC (yech!).
-
- So, if I am a normal person, why do I spend time writing this ?
- Well, because I have the insane urge to write thousands of words every now
- and then, and while I'm at it, I may do something productive, like teaching
- someone. I may be young, but I know a lot about computers (how humble I am;
- I know, modesty isn't one of my qualities).
-
- Just one more thing, if you ever program anything, please send to me... I
- would love to see some work you got, maybe I even could learn something with
- it. Also, give me a greet in your program/game/demo... I love seeing my
- name.
-
- ■ Contributions
-
- I as I stated before, I'm not a God... I do make mistakes, and I don't
- have (always) the best way of doing things. So, if you think you've spotted
- an error, or you have thought of a better way of doing things, let me know.
- I'll be happy to receive anything, even if it is just mail saying 'Keep it
- up'. As all human beings, I need incentive.
-
- Also, if you do like to write, please do... Send in articles, they will be
- welcome, and you will have the chance to see your names up in lights.
- They can be about anything, for a review of a book or program that can
- help a programmer, to a point of view or a moan.
-
- If anyone out there has a question or wants to see an article about
- something in particular, feel free to write... All letters will be answered,
- provided you give me your address.
-
- I'm also trying to start a new demo/game/utility group, and I need all sort
- of people, from coders (sometimes, one isn't enough), musicians (I can
- compose, but I'm a bit limited), graphics artists (I can't draw nothing) and
- spreaders... I mean, by a spreader, someone who spreads things, like this mag.
- If you have a BBS and you want it to include this magazine, feel free to
- write me...
-
- You can also contact me personally, if study on the IST (if you don't
- know what the IST is, you don't study there). I'm the freshman with the
- black hair and dark-brown eyes... Yes, the one that is occupying one of
- the X-terminals... I recommend you to contact me personally, if you can,
- especially if you are a member of the opposite sex (I'm a man, for those
- of you who are wondering).
-
- My adress is:
- Praceta Carlos Manito Torres, nº4/6ºC
- 2900 Setúbal
- Portugal
-
- Email: dgan@rnl.ist.utl
-
-
- ■ Hellos and greets
-
- I'll say hellos and thanks to all my friend, especially for those who put
- up with my constant whining (you know who you are).
- Special greets go to Denthor from Asphyxia (for the excelent VGA trainers),
- Draeden from VLA (for assembly tutorials), Joaquim Elder Guerreiro, alias
- Dr.Shadow (Delta Team is still up), Alex "Darkfox" (thanks for letting me
- use your BBS), Joäo Neves and Henrique Craveiro for sugestions, and all the
- demo groups out there.
- I also want to say hi to my idols (I know they don't read this, but...),
- Chris Roberts, François Lionet, Archer MacLean, everybody at ID Software and
- Apogee, Sierra On-Line, Lucas Arts and Team 17, for showing me what
- programming is all about.
-
-
-
-
- ■ Resolution of your homework
-
- In last issue, I chalenged you to make an improvement in the 'Maths'
- program I gave in Issue 1. Well, here's one of the possible improvements.
- This gives you the hability to choose the operation you want to execute.
-
- Program Maths(Input,Output);
-
- Var A,B:Integer;
- C,OP:Integer;
-
- Begin
- Writeln('The Maths Version 2.0');
- writeln;
- Writeln('1 - Add');
- Writeln('2 - Subract');
- Writeln('3 - Multiply');
- Writeln('4 - Divide');
- Writeln('5 - Remainder');
- Writeln;
- Write('Type in the number of the operation:');
- Readln(OP);
- Write('Type in number A : ');
- Readln(A);
- Write('Type in number B : ');
- Readln(B);
- If OP=1 Then C:=A+B;
- If OP=2 Then C:=A-B;
- If OP=3 Then C:=A*B;
- If OP=4 Then C:=A Div B;
- If OP=5 Then C:=A Mod B;
- Writeln;
- Writeln('The result is ',C);
- Writeln;
- Readln;
- End.
-
- This is quite simple... Depending on what operation you type in, the
- program executes the relevant calculation and prints out the result.
- There is still room from improvement in the program, but I leave to you
- decide what to do. You already know, if you have questions, mail them to me
- and I will answear them, or by mail or by the magazine.
-
-
-
- ■ Procedures and functions
-
- These are two of the more powerfull of Pascal's resources. These give you
- the hability to create new commands and functions. They are almost identical
- in the way they work, so I will explain deeply the procedure and then I will
- pass to the function, teaching you the diferences.
-
- ■ What are they ?
-
- Think of procedures like new commands, defined by you to do whatever you
- want. They are very usefull, as you will see. Let's say you have a program
- that writes the string 'Ok !' lots of time, and you don't want to spend time
- always writing "WRITELN('OK !')", what do you do? You use a procedure !!
-
- ■ How to use
-
- In the above example, you would do something like this: before the start of
- the main program block, write this:
-
- Procedure Writeok;
- Begin
- Writeln('Ok !');
- End;
-
- Then, everytime you would write "Writeok" in your program, the program would
- write 'OK !' in the screen. Let's see a working example:
-
- Program Test_8;
-
- Procedure Writeok;
- Begin
- Writeln('Ok !');
- End;
-
- Begin
- Writeln('How are you ?');
- Writeok;
- Readln;
- End.
-
- The above example is stupid, but it's just for you to get the picture.
- Notice that you can do ANYTHING you want in a procedure, just like in the
- main block. You can even call other procedures from it. A procedure is like
- an independant program, with it's one set of instructions and variables...
-
- ■ Local and global variables
-
- The procedure can have it's own variables, independants from the main
- program. Look at the next example:
-
- Program Test_9;
-
- Var B:Integer;
-
- Procedure Something;
- Var B:Word;
- Begin
- B:=10;
- Writeln('In the procedure, B=',B);
- End;
-
- Begin
- B:=5;
- Something;
- Writeln('In the main program, B=',B);
- Readln;
- End.
-
- See what I mean? The main program ignores the changes made to variable B
- inside the procedure. The variable B of the procedure is diferent of variable
- B in the main program.
- So, you come to a new concept. The variables defined outside the procedures
- are called GLOBAL VARIABLES, and those who are created inside of a procedure
- are called LOCAL VARIABLES.
- The diference between them is that global variables can be used in all
- program, not just in the main block, but in all procedures and functions,
- while local variables can only be used inside the place they are defined.
-
- ■ Parameters
-
- Imagine now that you wanted to make a procedure to do a complex calculation
- between the numbers 5 and 7. You would now use something that is called
- PARAMETERS. They are used like this:
-
- Procedure DoCalc(A,B:Integer);
- Var C:Integer;
- Begin
- C:=A+B*B;
- Writeln('The result is ',C);
- End;
-
- Now, you called the procedure like this:
-
- DoCalc(5,7);
-
- This works like this. The var A would get the value 5, and var B would get
- the value 7. Then, the procedure's main code would be executed and the result
- would be printed to the screen.
- A parameter can be anything, from a number to a string. You can even have
- different types of parameters, like this:
-
- Procedure Print(X,Y:Byte;S:String);
-
- You just use a semi-colon between them.
- I know this is a little confusing at first, because you're dealing with new
- concepts, but after you master this, you will get a priceless resource.
-
- ■ Functions
-
- The function is defined in the same way as the procedure, except that you
- use the keyword FUNCTION instead of the PROCEDURE keyword. They work the same
- way, but they have a diference. The function returns a value. This can be a
- number, a char or even a string. The sintax is a little diferent, because of
- this:
-
- Function DoCalc(A,B:Integer):Integer; { This defines function DoCalc, }
- { that requires two integers as }
- { parameters, and that returns }
- { and integer value }
- Var C:Integer; { Defines local variable C }
- Begin
- C:=A+B*B; { This executes the calculation }
- { and places the result in C }
- DoCalc:=C; { This tells the function to }
- { return the value in C. }
- End;
-
- Do call this, you would do something like this:
-
- D:=DoCalc(5,7); { D is a global variable, defined as an integer }
- Writeln(D);
-
- or
-
- Writeln(DoCalc(5,7); { This saves a variable }
-
- There isn't a rule for what to use, procedure or function. It depends on
- the program you are making. You can mix them up, having a procedure that calls
- a function or vice-versa. You can even call a procedure with a function as a
- parameter.
-
- There's a lot I haven't told you about procedures and functions, but I will
- leave that for a future issue. In next issue I will talk about loops and
- cicles. These are an almost essencial part of a program.
-
-
-
-
- ■ Introduction to assembly
-
- Somebody requested me to do an article about assembly, so here it is. This
- is a very simplistic view of it, but it should be enough to make you start
- coding some simple routines in Pascal with assembly.
- Don't forget that assembly language is very complicated, and only people
- that had a previous programming experience with some kind of high-level
- language should try to venture themselves in it.
- In the previous issue I explained some simple concepts of assembler, things
- like the what is the BIOS, interrupts and other things like that. I even
- explained how Pascal works with assembly. In the first issue, I explained
- what are bytes and bits and their relatives, so I will assume you already
- know that. So, without further due, I will talk about...
-
- ■ Segments and offsets
-
- This is the more annoying and complicated thing on the PC. Back in the time
- when dinossaurs ruled the Earth, the guys that designed the original 8088
- thought that nobody would ever need to address more than a meg (short for
- megabyte) of memory, so they decided to built a machine that couldn't access
- more than one meg of memory. But, for addressing one meg of memory, there was
- the need for a 20 bit number. Because this wasn't pratical, they've came up
- with a 'brilliant' way to do it. They would use two 16 bit registers. I know
- this adds up to a 32 bit number, but that's not the way it works. It works
- like this:
-
- Segment 0010100010001001
- Offset 0010101010100101
-
- 20 bit adress: 00101011001100110101 !!!!
-
- Here you have it... Segments and offsets combine to produce an absolute
- address of memory. The standart notation for the memory addresses is:
-
- Segment:Offset
-
- So, if somebody says that somethings in the address 6F1A:3652, that means
- that it is in the segment 6F1A (in hex, of course), offset 3652 (still in
- hex). Think of segments and offsets like this. The segment is the number of
- the page, and the offset is how far in the page the data is...
- Now, that you know what segments and offsets are, I can move on to...
-
- ■ Registers
-
- Registers are a special kind of variables, that are available to the
- processor. They perform various functions inside the CPU, and they are a very
- important part of assembly language. A list of their names, alongside with
- their uses follows:
-
- ■ AX
-
- AX (also called the accumulator) is a general purpose 16 bit register.
- It can be acessed as a word, or as two bytes, using AL or AH (the low
- and the high part).
- Examples:
- AX=10 => AL=10
- AH=0
-
- AX=256 => AL=1
- AH=1
-
- General rule, anything you do to AL or AH will influence AX, because
- you're manipulating it's low and high bytes.
- Before I forget: AX = AH * 256 + AL
- Do you understand it ?
- AX has some special uses. General rule it is the destination for
- memory grabs and multiplications. It's also plays a big part in port
- accessing.
-
- ■ BX (BH/BL)
-
- BX is just like AX... You can also access its lower and higher bytes.
- BX's special use is usually as an offset register.
-
- ■ CX (CH/CL)
-
- CX is just like AX and BX.
- It is used as a counter in loops.
-
- ■ DX (DH/DL)
-
- DX is like AX, BX and CX.
- It is used as destination is calculations and as a port index.
-
- ■ DI
-
- DI is a index register, a 16 bit register that is used for offsets.
- You can't access it's higher and lower bytes.
-
- ■ SI
-
- Same as DI, but usually DI is paired with the ES segment register,
- while SI is paired with the DS register.
-
- ■ DS
-
- This is a segment register, and it usually points to the Data Segment.
-
- ■ ES
-
- This is a segment register, that points to the Extra Segment.
-
- ■ FS
-
- This is like ES, but it only exists in the 386+.
-
- ■ GS
-
- Same as FS.
-
- The next registers you SHOULDN'T mess, unless you want your computer to
- crash.
-
- ■ BP
-
- Base pointer. This is an offset to use with the Stack Segment.
-
- ■ SP
-
- Stack pointer. This is an offset to use with the Stack Segment.
-
- ■ SS
-
- This is a segment register, that points to the Stack Segment.
-
- ■ CS
-
- This is a segment register, that points to the Code Segment.
-
- ■ IP
-
- This is the Intruction Pointer, that is used with CS.
-
-
- ■ The stack
-
- The stack is a temporary storage place, where data doesn't stay for long.
- It has the same principle of a stack of plates, except that the stack starts
- in the roof. This follows the order first in, last out, so, you must take the
- things in the reverse order that you put them in.
- I know this is confusing, but after some examples, you will feal right at
- home.
-
-
- ■ The flags
-
- The flags are like status indicators. They have all sort of indications for
- you to read and interpret. They only have the value true or false, and you
- can't access them directly.
- There are 17 flags, but you only have to know some of them:
-
- ■ Carry Flag (CF)
-
- The carry flag is used for many things. It's like a general purpose
- flag. It is one of the more used flags.
-
- ■ Parity Flag (PF)
-
- This flag is active when the value returned from last operation is
- even.
-
- ■ Zero Flag (ZF)
-
- This flag is set when the last operation returned a zero.
-
- ■ Overflow Flag (OF)
-
- This flag is set when the last operation went out of bounds.
-
- These are the ones mostly used. There are others, as stated before, but
- they aren't very used.
-
- ■ More about segments
-
- In pure assembly, you can define the segmentation of your program, but has
- we are using assembly with Pascal, we must use the Pascal's default
- segmentation, that is called Dos Segmentation. This means that there are four
- principal segments. There are addressed by CS, SS, DS, ES. They are called
- Code Segment, Stack Segment, Data Segment and Extra Segment.
-
- ■ Code Segment
-
- This is where your program resides. You probably now already that a
- segment can only have 64Kb of size, so you only get 64Kb for the code
- of your program. Now figure out why is it dangerous to change the CS
- register.
- One more thing about the CS register. It pairs up with the IP register
- to give the computer the address of the current instruction.
-
- ■ Stack Segment
-
- This is the place of the stack.
-
- ■ Data Segment
-
- This is where the data normally goes... It can go to other places,
- using pointers, but that's another story.
-
- ■ Extra Segment
-
- An extra segment for data.
-
- ■ Basic instructions
-
- Next, it follows a list of the essencial assembly instructions, the ones
- you should know from back to forth.
-
- ■ Mov
-
- This is the single more important instruction in Asm (short for
- assembly). The sintax is:
-
- Mov to,from
-
- The to and from parameters can be almost anything you want. Let's
- show some examples:
-
- Mov AX,40 This puts the imediate value 40 in AX
- Mov AL,20 This puts the imediate value 20 in AL
- Mov DH,10 This puts the imediate value 10 in DH
- Mov CX,BX This puts what's in BX in CX
- Mov AX,[DS:SI] This puts the word that is at DS:SI in AX
- Mov [ES:DI],BX This puts what's in BX in ES:DI
- Mov [ES:DI+5],CX This puts what's in CX in ES:DI+5
- Mov DX,[x] This puts what's in var x in DX
-
- This is easy enough.
-
-
- ■ Int
-
- I already talked about this command in last issue. This command calls
- up an interrupt. Sintax:
-
- Int n
-
- Examples:
- Int 10h This calls interrupt 10 (in hex)
- Int 10 This calls interrupt 10 (in dec)
-
-
- ■ Stosb
-
- This stores what's in AL in destination ES:DI, and then increments
- DI by one. It hasn't got any parameters.
-
- ■ Stosw
-
- Just like Stosb, but is transfers whats in AX and increments Di by
- two.
-
- ■ Movsb
-
- This moves the byte that is in DS:SI to ES:DI, and then increments
- SI and DI by one.
-
- ■ Movsw
-
- This moves the word as DS:SI to ES:DI, and then increments SI and DI
- by two.
-
- ■ Add
-
- Sintax:
- Add dest,source
-
- This adds source to dest and stores the result in dest. Dest can't be
- and imediate value, as obvious.
-
- ■ Sub
-
- Sintax:
- Sub dest,source
-
- This subtracts source from dest and stores the result in dest.
-
- ■ Mul
-
- Sintax:
- Mul source
-
- This multiplies source by AX (if source is a word) or by AL (if
- source is a byte). The result is stored in AX (if source is a byte)
- or in DX:AX (if source is a word).
-
- ■ Push
-
- This pushes something onto the stack. The sintax is:
-
- Push source
-
- Source can be a register or an immediate value.
-
- ■ Pop
-
- This takes off something off the stack. The sintax is:
-
- Pop dest
-
- Dest is where you want to put the value you take.
- Remember what I said about first in, last out ?
- Take a look at these examples:
-
- Mov ax,5 AX=5
- Push ax Puts AX in the stack
- Mov ax,10 AX=10
- Pop ax Takes the last value put in the stack,
- in this case, AX=5
-
- Mov ax,10
- Mov bx,5
- Push ax
- Push bx This piece of code would swap the values of AX and
- Pop ax BX. Because first in is the last out.
- Pop bx
-
- So, that's about it... There's lots of other things, but this should cover
- up the basic. Get some source codes and experiment with them. If you have
- any doubts, drop me a line and I'll try to explain myself better. If you
- want some source code, feel free to ask me some...
-
-
-
- ■ Graphics, part II : Palettes
-
- ■ Introduction
-
- The palette is a mistery to most programmers, even professional ones, and
- often overlooked as beeing not too important. But I'm of those who think
- that the palette and effects derived from it have a great potencial. To see
- what I'm saying, just execute the 'Color Blind' demo I made especially for
- the magazine. I made it in a couple of days, and I think it's fairly good,
- considering that it pratically just uses the palette.
-
- ■ What's the palette
-
- A palette is a place where colors are stored. Has you should already now,
- the mode 13h palette has 256 colors. Each one has a number, ranging from 0
- to 255, and an intensity value for each of it's components.
- In the PC, as in real life, colors are the result of the mixture of
- primary colors. You should have learned about it in the 5th grade. But, in
- real life, the primary colors are blue, yellow, magenta, black and white.
- In computerland, there are only three basic colors: red, green and blue.
- Each one of them can be mixed together in diferent ammounts.
- But (there's always a but everywhere), NEVER forget that two colors can
- look just the same in the screen and be completely different. Also, don't
- forget that when you alter the palette, all the pixels in the screen drawn
- with that color will be changed. For example, imagine you just set color 53
- and 80 with the same RGB (short for red,green and blue components), and
- filled the screen with pixels color 53 and 80. Well, when you looked at the
- screen, it would look like it was filled with the same color, but when you
- changed color 80, the entire screen would change the look entirely.
-
- ■ How to set and get the palette
-
- This is easy. You just have to remember that everything concerning the
- palette is done through the ports 3C7h, 3C8h and 3C8h.
- So, let's get the palette of a specific color. All you have to do is to
- enter the number of the color you want into port 3C7h and then read in the
- values of the red, green and blue components from port 3C9h. For acessing
- the ports, you use a Pascal defined array that is called PORT. It is
- something like the MEM array. The sintax is:
-
- Port[number of the port]
-
- So, a procedure to read in the RGB values of one color would be like
- this:
-
- Procedure GetColor(Col:Byte;Var R,G,B:Byte);
- Begin
- Port[$3C7]:=Col;
- R:=Port[$3C9];
- G:=Port[$3C9];
- B:=Port[$3C9];
- End;
-
- To set the palette, it's almost the same... You put the number of the
- color you want to change into port 3C8h and then put the values in port
- 3C9h, in the order red, green and blue. Remember that the intensity is a
- number from 0 to 63.
-
- Procedure SetColor(Col,R,B,G:Byte);
- Begin
- Port[$3C8]:=Col;
- Port[$3C9]:=R;
- Port[$3C9]:=G;
- Port[$3C9]:=B;
- End;
-
- This is very easy, tough it has some quirks...
- Now, let's go to something harder... Setting the whole palette !!
- The way I do it is like this: first I define two records, one to store
- the RGB value of one color and the other to store the whole palette.
-
- Type RgbItem=Record
- R,G,B:Byte;
- End;
- RgbList=Array[0..255] of RgbItem;
-
- Then, you define the procedure to read the palette into a var of the
- predefined type:
-
- Procedure GetPalette(Var Pal:RgbList);
- Var A:Byte;
- Begin
- For A:=0 To 255 do GetColor(A,Pal[A].R,Pal[A].G,Pal[A].B);
- End;
-
- You just get the colors of the 256 colors and store them into an array,
- where you can change them at you will. To set the whole palette, just do
- the same, like this:
-
- Procedure SetPalette(Pal:RgbList);
- Var A:Byte;
- Begin
- For A:=0 To 255 do SetColor(A,Pal[A].R,Pal[A].G,Pal[A].B);
- End;
-
- As you see, it's fairly easy... But, if you are brave, you'll probably
- just went and tried the routines. If you do so, you will be disapointed with
- the results. You'll probably get a screen full of "snow". The "Snow" is the
- dots that appear in your screen when you change colors.
-
- ■ The retrace
-
- So, how can you stop this? First, you must understand something about
- monitor theory. As you may already know, the image in your screen is updated
- by an electron beam, that sweeps the screen, from left to right. When it
- reaches the end of a line, it goes to another line. When it reaches the end
- of the screen, the electron beam resets to it's initial position in the
- upper left corner. This period, while the beam goes from the lower right
- corner to the upper left one, is called the Vertical Retrace, or Vertical
- Blank. How is this helpfull? Well, during this period, anything you do to
- the screen won't show imediatly, so, you can change the palette, draw
- sprites, or anything else, and it would only show in the next retrace. But,
- everything has a downside, and the VBL (Vertical BLank) is no exception. The
- period is very, very short. So that you'll know, it occurs a VBL almost 70
- times a second, so, anything you want to do you'll have to do it fast... You
- should use frequenty the retrace, especially when you do lot's of thing on
- the screen.
- But this is enough for setting the whole palette without fuzz. The
- following procedure waits first for the retrace to begin. It is all in
- assembler, and it's quite complicated. To the tech-minded out there, we
- simply get a byte from port 3DAh. If the third bit of the byte is set,
- that means that VBL in occuring.
-
- Procedure WaitVBL; Assembler;
- Label A1,A2;
- Asm
- Mov DX,3DAh
- A1:
- In AL,DX
- And AL,08h
- Jnz A1
- A2:
- In AL,DX
- And AL,08h
- Jz A2
- End;
-
- So, here you have it... A procedure to test the VBL. Now, the SetPalette
- procedure should be like this:
-
- Procedure SetPalette(Pal:RgbList);
- Var A:Byte;
- Begin
- WaitVBL;
- For A:=0 To 255 do SetColor(A,Pal[A].R,Pal[A].G,Pal[A].B);
- End;
-
- Easy, isn't it ?...
-
- ■ Palette effects
-
- Now, I will talk about two types of effects, and the application of one
- of them. The palette by it's own is capable of some nice effects, as I think
- I've shown in my Color Blind demo.
-
- ■ Rotations
-
- Rotating the palette is a good effect to start coding, and a very
- effective one. Most of the effects in Color Blind are diferent types of
- rotations.
- Rotating the palette is just a matter of making color 0 be color 1,
- color 1 be color 2, and so forth, until color 255 be color 0. You can also
- do a reverse rotation, just by changing the direction. Code follows:
-
- Procedure RotatePal(Var Pal:RgbList);
- Var Temp:RgbItem;
- A:Byte;
- Begin
- Temp:=Pal[255];
- For A:=254 DownTo 0 Do
- Begin
- Pal[A+1]:=Pal[A];
- End;
- Pal[0]:=Temp;
- End;
-
- Study this piece of code, I think it's very simple. This rotates the
- colors of a palette buffer (type RgbList), not the colors of the screen.
- After you rotate the buffer, you'd still have to set them, so you'll
- notice the effect. It can be done with something like this:
-
- Var Pal1:RgbList;
- .......
- .......
- GetPalette(Pal1);
- Repeat
- RotatePal(Pal1);
- SetPalette(Pal1);
- Until Keypressed;
- .......
- .......
- .......
-
- This would rotate the palette of the screen until some key is pressed.
- Now, let's move forth to a tougher effect:
-
- ■ Fades
-
- If you watch TV (and who doesn't ?), you'll see that most of the times,
- the images don't just appear out of nowhere. They slowly fade in or out,
- the colors slowly transforming to do the image. Well, it's fairly easy to
- do so in the PC, and it is a bonus, because it's more impressive to see
- the image slowly appearing than throwing it to the screen altogether.
- The theory behind a fade is fairly simple. You have a source pallete
- (usually the screen palette) and a target palette. Than, you compare
- each color and increase or decrease their RGB values.
- You compare the RGB values of color 0 of the source palette with the
- RGB values of color 0 of target palette, and change their values in face
- of that. The next piece of code was the first fade I've ever made, and it
- is very badly done. It can be done a lot faster and prettier, but I leave
- that to you.
-
- Procedure Fade(Target:RgbList);
- Var Tmp:RgbList;
- Flag:Boolean;
- Loop:Integer;
- Begin
- Repeat
- Flag:=True;
- GetPalette(Tmp);
- For Loop:=0 To 255 Do
- Begin
- If Tmp[Loop].R>Target[Loop].R Then
- Begin
- Dec(Tmp[Loop].R);
- Flag:=False;
- End;
- If Tmp[Loop].G>Target[Loop].G Then
- Begin
- Dec(Tmp[Loop].G);
- Flag:=False;
- End;
- If Tmp[Loop].B>Target[Loop].B Then
- Begin
- Dec(Tmp[Loop].B);
- Flag:=False;
- End;
- If Tmp[Loop].R<Target[Loop].R Then
- Begin
- Inc(Tmp[Loop].R);
- Flag:=False;
- End;
- If Tmp[Loop].G<Target[Loop].G Then
- Begin
- Inc(Tmp[Loop].G);
- Flag:=False;
- End;
- If Tmp[Loop].B<Target[Loop].B Then
- Begin
- Inc(Tmp[Loop].B);
- Flag:=False;
- End;
- End;
- SetPalette(Tmp);
- Until Flag;
- End;
-
- This is very straighforward, and very simple. You just check all the
- 256 colors until they all reach their target counterpart. This procedure
- can be expanded to allow speed control and other things like that, but
- it works fine just as it is. For example, to fade out a screen (to fade
- to black), you just set all colors in the target palette to 0 and then
- fade the screen.
- Now, we'll go on to discuss a pratical way to use the palette
- rotations.
-
- ■ The static screen
-
- If you saw the Color Blind demo, you'll notice one of the last effects:
- the static screen. This is a screen full of static (like if you tune the
- TV to an unused station). This is simple to code, and impressive, never
- the less, if coupled with some other effects, like a text scroll or a
- fade in/out kind of stuff like in Color Blind.
- To do a static screen, you must first define a pallete in which the
- first 16 colors are greys, like this:
-
- Procedure SetGreys(Var Pal:RgbList);
- Var A:Byte;
- Begin
- For A:=0 to 15 Do
- Begin
- Pal[A].R:=A*4;
- Pal[A].G:=A*4;
- Pal[A].B:=A*4;
- End;
- End;
-
- Then, you fill the screen with the first 16 colors, using the Random
- function to maximaize the effect.
-
- Procedure FillScreen;
- Var X,Y:Integer;
- Begin
- For Y:=0 to 199 Do For X:=0 to 319 Do PutPixel(X,Y,Random(15));
- End;
-
- Finally, you cicle the 16 first colors. To do this, you'll have to
- change a bit the RotatePal procedure. It must be something like this:
-
- Procedure RotatePal(Var Pal:RgbList;First,Last:Byte);
- Var Temp:RgbItem;
- A:Byte;
- Begin
- Temp:=Pal[Last];
- For A:=Last-1 DownTo First Do
- Begin
- Pal[A+1]:=Pal[A];
- End;
- Pal[First]:=Temp;
- End;
-
- To rotate the 16 first colors, you'll have to do something like this:
-
- RotatePal(Pal1,0,15);
-
- I assume your palette buffer is called Pal1.
- So, here you have it... You personal untuned TV.
-
-
- Program Static_Screen;
-
- Uses Crt;
-
- Const VGA=$A000;
-
- Type RgbItem=Record
- R,G,B:Byte;
- End;
- RgbList=Array[0..255] of RgbItem;
-
- Var Pal1:RgbList;
-
- Procedure Initgraph; Assembler;
- Asm
- Mov AH,0
- Mov AL,13h
- Int 10h
- End;
-
- Procedure Closegraph; Assembler;
- Asm
- Mov AH,0
- Mov AL,03h
- Int 10h
- End;
-
- Procedure WaitVBL; Assembler;
- Label A1,A2;
- Asm
- Mov DX,3DAh
- A1:
- In AL,DX
- And AL,08h
- Jnz A1
- A2:
- In AL,DX
- And AL,08h
- Jz A2
- End;
-
- Procedure PutPixel(X,Y,C:Word);
- Begin
- Mem[VGA:(Y*320)+X]:=C;
- End;
-
- Procedure GetColor(Col:Byte;Var R,G,B:Byte);
- Begin
- Port[$3C7]:=Col;
- R:=Port[$3C9];
- G:=Port[$3C9];
- B:=Port[$3C9];
- End;
-
- Procedure SetColor(Col,R,B,G:Byte);
- Begin
- Port[$3C8]:=Col;
- Port[$3C9]:=R;
- Port[$3C9]:=G;
- Port[$3C9]:=B;
- End;
-
- Procedure GetPalette(Var Pal:RgbList);
- Var A:Byte;
- Begin
- For A:=0 To 255 do GetColor(A,Pal[A].R,Pal[A].G,Pal[A].B);
- End;
-
- Procedure SetPalette(Pal:RgbList);
- Var A:Byte;
- Begin
- WaitVBL;
- For A:=0 To 255 do SetColor(A,Pal[A].R,Pal[A].G,Pal[A].B);
- End;
-
- Procedure SetGreys(Var Pal:RgbList);
- Var A:Byte;
- Begin
- For A:=0 to 15 Do
- Begin
- Pal[A+1].R:=A*4;
- Pal[A+1].G:=A*4;
- Pal[A+1].B:=A*4;
- End;
- End;
-
- Procedure SetBlack(Var Pal:RgbList); { This sets the buffer to black }
- Var A:Byte;
- Begin
- For A:=0 to 255 Do
- Begin
- Pal[A].R:=0;
- Pal[A].G:=0;
- Pal[A].B:=0;
- End;
- End;
-
- Procedure FillScreen;
- Var X,Y:Integer;
- Begin
- For Y:=0 to 199 Do For X:=0 to 319 Do PutPixel(X,Y,Random(15));
- End;
-
- Procedure RotatePal(Var Pal:RgbList;First,Last:Byte);
- Var Temp:RgbItem;
- A:Byte;
- Begin
- Temp:=Pal[Last];
- For A:=Last-1 DownTo First Do
- Begin
- Pal[A+1]:=Pal[A];
- End;
- Pal[First]:=Temp;
- End;
-
- Procedure Fade(Target:RgbList);
- Var Tmp:RgbList;
- Flag:Boolean;
- Loop:Integer;
- Begin
- Repeat
- Flag:=True;
- GetPalette(Tmp);
- For Loop:=0 To 255 Do
- Begin
- If Tmp[Loop].R>Target[Loop].R Then
- Begin
- Dec(Tmp[Loop].R);
- Flag:=False;
- End;
- If Tmp[Loop].G>Target[Loop].G Then
- Begin
- Dec(Tmp[Loop].G);
- Flag:=False;
- End;
- If Tmp[Loop].B>Target[Loop].B Then
- Begin
- Dec(Tmp[Loop].B);
- Flag:=False;
- End;
- If Tmp[Loop].R<Target[Loop].R Then
- Begin
- Inc(Tmp[Loop].R);
- Flag:=False;
- End;
- If Tmp[Loop].G<Target[Loop].G Then
- Begin
- Inc(Tmp[Loop].G);
- Flag:=False;
- End;
- If Tmp[Loop].B<Target[Loop].B Then
- Begin
- Inc(Tmp[Loop].B);
- Flag:=False;
- End;
- End;
- SetPalette(Tmp);
- Until Flag;
- End;
-
- Begin
- Initgraph;
- SetBlack(Pal1);
- SetPalette(Pal1);
- FillScreen;
- SetGreys(Pal1);
- Fade(Pal1);
- Repeat
- RotatePal(Pal1,1,16);
- SetPalette(Pal1);
- Until KeyPressed;
- SetBlack(Pal1);
- Fade(Pal1);
- Closegraph;
- Writeln('Another SpellCaster production... The Static Screen...');
- Writeln('Press RETURN to quit...');
- Readln;
- End.
-
- So, here you have it... The Static Screen. I like this effect very much.
- I was to include also a part about the cross-fade effect, but it's a lot
- more complicated and requires other knowledge. As soon as I feel you're
- ready, I'll make a tutor on it too.
-
-
-
- ■ Points of view
-
- Well, I have bad news for all fans out there... I'm going to start school
- tomorrow, so, I think the next issue of 'The Mag' will be slightly delayed,
- because I'm moving to a new scholl that's almost 50 km from where I live, and
- I don't know anything nor anyone there, so I don't think I can prepare the
- next issue in time... But don't worry, I'll still be making the magazine, for
- all coders and would-be coders out there.
- I also don't have time because I'm going to start coding a new game...
- I don't know the name for it, nor the kind of game it will be, but I have some
- ideas. If you would like to make a sugestion, feel free to write. I need input
- from all of you out there on what kind of game is the favourite amongst you.
- I was writing a game, called "Titans", a strategy wargame, but because of
- my insane ambition, I can't do it without learning first how to work with
- Extended and Expanded memory. If anyone out there knows, type me a letter.
- So, I think this is goodbye... I think this was a great issue, with assembly
- and other stuff in it. If you think so too, write to me and say something.
-
-
-
- ■ The adventures of Spellcaster, the rebel programmer of the year 2018.
-
- Episode 3 - Escape
-
- Everything is set now. After one month of pure disgust, I'ver learned to
- program the Atari, at least enough to make a virus powerfull enough to disable
- the prison's power grid. I've just finished my chores, so I can go now to the
- computer center and activate the virus.
- I walked slowly, fearing that some guard noticed my thoughts, and prevented
- my long-awayted freedom. I walked until the room. The guard in the door
- looked at me, as if it could read my mind, and smilled with a grin, making me
- a signal to enter. I went inside the gloomy room. It was cold and dark, only
- the brightness of the monitors to lighten it up. There it was... The Atari
- 520ST, with it's patetic 32 color display. I sat down at the keyboard and
- closed my eyes. It was still hard for me to look at that disgusting thing. I
- typed away, and an half-hour later, everything was done. I prepared the virus
- to go active at two o'clock in the morning. Then, I returned to my chambers,
- where I lyed down, with my eyes open. At 11:00, the lazer bars were activated
- and the lights were turned off. I looked at the entry to my cell, staring at
- the red light that crossed it, knowing that this was probably the last time
- I would see them.
- At precisely 2:00, the red light went off. Seconds later, I got up and
- started walking quitly by the walkway, trying to make no noise. I felt someone
- breathing in my neck, I turned my head and I saw that I was beeing followed.
- The other inmates also noticed the power shortage. Suddently, lazer shots were
- heard, and screams raised all around. The guards noticed us and were firing.
- I start running, followed by another convict, and I knocked a guard over,
- jumping over him and punching him until he was dead... I didn't had conscience
- problems... I got up and continued running. In a few minutes, I was out of the
- prison's gates, and I suddently stopped. The taste of freedom filled my mouth,
- when I was knocked over by someone, followed by a stream of lazer shots, that
- hitted the ground where I stood. The person that was now on top of me saved my
- life! I pushed him of me, then got up, helping the other man getting up. It was
- a tall, blond man, that smilled at me. I looked at him and smilled back. Then,
- we both started running, as there was no tomorrow, until we could run no more.
- I drop down to my knees and looked back. At some distance, I could still hear
- screams and lazer shots of the Atari Penetenciary. Then, I noticed that the
- tall man was still behind me, looking forward. I looked forward and saw the
- Atlantic Ocean right in front of me. Then I yelled, as loud as I could:
- - I'M FREE !!!!!!!
-
-
- See you in the next issue
- Diogo "SpellCaster" Andrade
-